<!--
 * @Author: 邵渊
 * @Description: file 文件上传
-->

<template>
  <div class="lc-file">
    <el-upload
      v-if="showEnter"
      class="lc-upload"
      v-bind="$props"
      :on-preview="handlePreview"
      :on-exceed="handleExceed"
      :on-success="handleSuccess"
      :on-error="handleError"
      :on-change="handleChange"
      :on-remove="handleRemove"
      :before-remove="beforeRemove"
      :on-progress="handleProgress"
      :file-list="fileList"
      :auto-upload="false"
      :show-file-list="false"
    >
      <slot></slot>
      <template v-if="uploadTip" #tip>
        <div class="el-upload__tip">
          {{ uploadTip }}
        </div>
      </template>
      <!-- <template v-if="drag">
        <div class="lc-upload__add">
          <i class="el-icon-upload2" :class="limit == fileList.length ? 'is-disabled' : ''" />
          <span>添加文件</span>
          <span class="lc-upload__add-limit" v-if="limit"> {{ fileList.length }}/{{ limit }}</span>
        </div>
        <div class="lc-upload__desc" v-if="maxsize">
          单个文件不超过<span>{{ maxsize }}</span>
        </div>
      </template> -->
    </el-upload>

    <div v-if="showFileList && showType === 'list'" class="lc-file-list">
      <template v-for="(item, index) in fileList" :key="item.key || index">
        <div class="lc-file-list__item">
          <lc-svg-icon
            :icon-class="getFileIcon(item.fileType)"
            class-name="lc-file-list__item-icon"
          />
          <span class="lc-file-list__item-label" :title="item.name">{{ item.name }}</span>
          <span class="lc-file-list__item-operates lc-file-button">
            <el-button link type="primary" @click="handleFileDeleteItem(item)">删除</el-button>
            <el-button link type="primary" @click="handleFileDownLoad(item)">下载</el-button>
          </span>
        </div>
      </template>
    </div>
    <!-- table展示 -->
    <el-table
      v-if="showFileList && showType === 'table' && fileList.length"
      :data="fileList"
      class="lc-file-show-table"
    >
      <el-table-column prop="name" label="文件名" min-width="150px" />
      <el-table-column prop="handle" label="操作" min-width="110px">
        <template v-slot="{ row }">
          <el-button link type="primary" @click="handleFileDeleteItem(row)">删除</el-button>
          <el-button link type="primary" @click="handleFileDownLoad(row)">下载</el-button>
        </template>
      </el-table-column>
    </el-table>
  </div>
</template>

<script setup>
import { downloadFile } from '@/utils/common';
import { fileDownload } from '@/apis/file';
import { request } from '@/apis/request';
import { computed, ref, watch } from 'vue';
import { ElMessage } from 'element-plus';
const props = defineProps({
  modelValue: {
    type: Array,
    default: () => []
  },
  // 上传文件地址
  action: {
    type: String,
    default: 'https://jsonplaceholder.typicode.com/posts/'
  },
  // 上传url请求类型
  method: {
    type: String,
    default: 'post'
  },
  // 设置上传的请求头部
  headers: {
    type: Object,
    default: () => ({})
  },
  // 上传时附带的额外参数
  data: {
    type: Object,
    default: () => ({})
  },
  // 是否支持多文件
  multiple: {
    type: Boolean,
    default: true
  },
  // 最大允许上传个数
  limit: {
    type: Number,
    default: 1
  },
  // 接受上传的文件类型
  accept: {
    type: String,
    default: ''
  },
  // 文件最大大小
  maxsize: {
    type: String,
    default: ''
  },
  // 是否展示文件列表
  showFileList: {
    type: Boolean,
    default: false
  },
  // 是否支持拖拽
  drag: {
    type: Boolean,
    default: false
  },
  // 上传回显形式 表格/列表
  showType: {
    type: String,
    default: 'list'
  },
  // 是否显示上传入口
  showEnter: {
    type: Boolean,
    default: true
  },
  resDataName: {
    type: String,
    default: 'data'
  }
});
const emits = defineEmits(['update:modelValue']);
const fileList = ref(props.modelValue || []);
const uploadTip = computed(() => {
  if (props.accept && props.maxsize) {
    return `只能上传${props.accept}文件，且不超过${props.maxsize}`;
  } else if (props.accept) {
    return `只能上传${props.accept}文件`;
  } else if (props.maxsize) {
    return `文件大小不超过${props.maxsize}`;
  } else {
    return false;
  }
});
watch(fileList, (val) => {
  emits('update:modelValue', val);
});
function handlePreview() {
  console.log('preview');
}
function handleExceed(files, _fileList) {
  ElMessage.warning({
    message: `当前限制选择 ${props.limit} 个文件，本次选择了 ${files.length} 个文件，共选择了 ${
      files.length + _fileList.length
    } 个文件`
  });
}
function handleSuccess(response, file, _fileList) {
  console.log('success');
}
function handleError(err, file, _fileList) {
  console.log('error');
}
function handleChange(file, _fileList) {
  const uid = file.uid;
  // 组装请求参数
  const formData = new FormData();
  formData.append('file', file.raw);
  for (const i in props.data) {
    formData.append(i, props.data[i]);
  }
  // 更新文件列表
  fileList.value = _fileList.map((item) => {
    const fileType = item.name.split('.').slice(-1)[0];
    return {
      uid: item.uid || '',
      name: item.name,
      fileType,
      fileCode: item.fileCode || ''
    };
  });
  // 发起请求
  request(
    {
      url: props.action,
      method: props.method,
      headers: props.headers,
      data: formData
    },
    {
      isShowLoading: false
    }
  )
    .then((res) => {
      if (res[props.resDataName]) {
        const obj = fileList.value.find((e) => e.uid === uid);
        obj && (obj.fileCode = res.data);
      } else {
        const index = fileList.value.findIndex((e) => e.uid === uid);
        fileList.value.splice(index, 1);
      }
    })
    .catch((error) => {
      ElMessage.error({ message: error });
      // 加个延迟，展示失败后删除的过程
      setTimeout(() => {
        const index = fileList.value.findIndex((e) => e.uid === uid);
        fileList.value.splice(index, 1);
      }, 300);
    });
}
function handleRemove() {
  console.log('remove');
}
function beforeRemove() {
  console.log('before-remove');
}
function handleProgress(event, file, fileList) {
    // 计算上传进度
    // const progress = Math.ceil((event.loaded / event.total) * 100);

    // 将进度赋给进度条的 percentage 属性
    // file.percentage = progress;

    // 如果不使用 file.percentage 属性，而是使用 fileList 的方式更新进度条，请参考下面的代码
    // const index = fileList.findIndex(item => item.uid === file.uid);
    // fileList[index].percentage = progress;

    // 强制更新 DOM
    // this.$forceUpdate();
}
/**
 * 事件回调
 */
function handleFileDeleteItem(item) {
  fileList.value.splice(fileList.value.indexOf(item), 1);
}
function handleFileDownLoad(item) {
  fileDownload({
    fileCode: item.fileCode,
    isOnline: false
  }).then((res) => {
    downloadFile(res, item.name);
  });
}
function getFileIcon(fileType) {
  switch (fileType) {
    case 'xls':
    case 'xlsx':
      return 'file-excel';
    case 'gif':
      return 'file-gif';
    case 'pdf':
      return 'file-pdf';
    case 'ppt':
      return 'file-ppt';
    case 'txt':
      return 'file-txt';
    case 'word':
      return 'file-word';
    case 'wps':
      return 'file-wps';
    case 'jpg':
    case 'jpeg':
    case 'png':
    case 'bpm':
    case 'tif':
    case 'svg':
      return 'file-picture';
    case 'mp3':
    case 'wav':
    case 'wma':
      return 'file-audio';
    case 'mp4':
    case 'avi':
    case 'wmv':
    case 'mpg':
    case 'mpeg':
    case 'mov':
    case 'rm':
    case 'ram':
    case 'swf':
    case 'flv':
      return 'file-video';
    case 'zip':
    case 'rar':
    case '7z':
      return 'file-yasuobao';
    default:
      return 'file-default';
  }
}
</script>

<style lang="scss" scoped>
.lc-file {
  .lc-file-button,
  .lc-file-show-table {
    .el-button {
      min-width: 30px;
      padding: 0;
    }
    .el-button + .el-button {
      margin-left: 10px;
    }
  }
}
</style>
